/**
 * @file      uplink_manager.c
 * @brief
 * @version   1.0
 * @date      2023.12.14
 *
 * @copyright Copyright (c) 2018 UCchip Technology Co.,Ltd. All rights reserved.
 *
 * Change Logs:
 * Date          Author       Notes
 * 2023.12.14    ucchip       the first version
 *
 */

#include "uplink_manager.h"
#include "auth_manager.h"
#include "config_api.h"
#include "downlink_manager.h"
#include "interaction_manager.h"
#include "led_manager.h"
#include "manager_queue_comm.h"
#include "module_queue_struct.h"
#include "net_app.h"
#include "net_prot.h"
#include "ota_manager.h"
#include "roll_call_manager.h"
#include "state_manager.h"
#include "time_slot_manager.h"
#include "tiny_base64.h"
#include "uc_coding.h"
#include "uc_hex.h"
#include "userid_manager.h"
#include "watchdog_app.h"
#include <rtdevice.h>
#include <rtthread.h>

#define DBG_ENABLE
#define DBG_SECTION_NAME "ul_mn"
#include "uc_log.h"

// WIoTa协议栈版本，启动完成后获取
wiota_version_t g_wiota_version = {0};

static unsigned int get_diff_tick(unsigned int new_tick, unsigned int old_tick)
{
    unsigned int diff_tick = 0;

    if (new_tick >= old_tick)
    {
        diff_tick = new_tick - old_tick;
    }
    else
    {
        diff_tick = 0xFFFFFFFF - old_tick + new_tick;
    }

    return diff_tick;
}

void manager_gateway_userid_init(void)
{
    id_manager_cfg_t *id_mng_cfg = (id_manager_cfg_t *)uc_static_get_gateway_id_manager_cfg();
    // 透传模式，无需id管理
    if (UC_TRANSMISSION_MODE == uc_static_get_gateway_auth_cfg()->work_mode)
    {
        TRACE_W("TRANSMISSTION_MODE not require to init userid manager");
        return;
    }

    // 已经初始化了，无需再次初始化
    if (USERID_MANAGE_DEFAULT != manager_get_userid_manager_state())
    {
        TRACE_W("userid manager already initialized");
        return;
    }

    if (0 == manager_wiota_userid_init(id_mng_cfg))
    {
        manager_set_userid_manager_state(USERID_MANAGE_INIT);
    }
    else
    {
        TRACE_E("manager_wiota_userid_init fail, restart gateway now!");
        rt_thread_mdelay(100);
        watchdog_reboot();
    }
}

/**
 * @brief 广播时隙信息回调函数
 *
 */
void manager_bc_time_slot_callback(time_slot_bc_t *time_slot_info)
{
    // 周期将time_slot_info发送给所有终端，打包后发到wiota app线程
    app_ps_header_t ps_header = {0};
    unsigned char *output_data;
    unsigned int output_len;
    unsigned char gw_verity = uc_static_get_gateway_auth_cfg()->gw_verity;
    unsigned int gw_dev_id = uc_static_get_gateway_base_cfg()->dev_id;

    // id管理未初始化，不能发送数据
    if (USERID_MANAGE_INIT != manager_get_userid_manager_state())
    {
        TRACE_W("addr_state is not init, not require to bc time_slot");
        return;
    }

    // 如果处于扫频状态，则不处理任何消息
    if (manager_get_scan_freq_state())
    {
        // TRACE_W("WIoTa is scanning freq, ignore bc_time_slot!");
        return;
    }

    ps_header.cmd_type = AUTHENTICATION_BC_TIME_SLOT;

    // 开启网关验证后，下行数据添加src_addr，终端收到后做验证
    if (gw_verity)
    {
        app_set_header_property(PRO_SRC_ADDR, 1, &ps_header.property);
        ps_header.addr.src_addr = gw_dev_id;
    }

    if (0 == app_data_coding(&ps_header, (unsigned char *)time_slot_info, sizeof(time_slot_bc_t), &output_data, &output_len))
    {
        if (0 != manager_send_to_wiota(GATEWAY_MANAGER_MODULE,
                                       WIOTA_APP_SEND_BC_AUTH_TS,
                                       0,
                                       gw_dev_id,
                                       0,
                                       output_data,
                                       output_len,
                                       RT_NULL))
            rt_free(output_data);
    }
    else
    {
        TRACE_E("bc time_slot coding error");
    }
}

/**
 * @brief AP帧号刷新回调
 *
 * @param frame_num 帧号
 */
static void manager_fn_refresh_callback(unsigned int frame_num)
{
    // 根据帧号获取sf_info，这个结构包含了，该时隙定帧收发的所有信息
    sf_info_t *sf_info = manager_get_sf_info_by_fn(frame_num);

    // note, 处于扫频状态时，帧号不会刷新，可以不加判断manager_get_scan_freq_state()
    // sf_info不为空时表示有效，且可以安排该业务时隙的收发任务
    if (sf_info != RT_NULL)
    {
        module_queue_communication(module_get_queue(WIOTA_APP_MODULE),
                                   GATEWAY_MODULE_DEFAULT,
                                   WIOTA_APP_MODULE,
                                   WIOTA_APP_RS_SM_BY_FN,
                                   sf_info);
    }
}

void manager_gateway_time_slot_init(void)
{
    slot_rs_cfg_t *slot_rs_cfg = (slot_rs_cfg_t *)uc_static_get_slot_send_cfg();
    unsigned char gw_mode = uc_static_get_gateway_auth_cfg()->work_mode;

    if (gw_mode != UC_TRANSMISSION_TIME_SLOT_MODE || slot_rs_cfg->data_transport_period == 0)
    {
        // TRACE_E("ul_send_period is 0, not require to init time_slot_info");
        return;
    }

    if (0 == manager_time_slot_info_init(slot_rs_cfg, manager_bc_time_slot_callback, manager_fn_refresh_callback))
    {
        uc_static_save_op();
        TRACE_I("save slot_send_cfg_static");
    }

    // 该模式下单播的网关重发次数为0，且协议栈重发次数根据分时收发配置来决定
    wiota_rate_cfg_t *rate_cfg = uc_static_get_wiota_rate_cfg();
    rate_cfg->uc_resend_times = 0;
}

/**
 * @brief 定帧收发反初始化
 *
 */
void manager_gateway_time_slot_deinit(void)
{
    sf_info_t *sf_info = manager_get_sf_info_addr();
    unsigned char ul_subf_num = manager_get_ul_subframe_num();
    sf_data_node_t *data_node = RT_NULL;
    mng_to_wiota_data_t *dl_data = RT_NULL;

    manager_time_slot_info_deinit();

    // 该结构需要用户自己释放，因为不知晓data_node->data的结构
    if (sf_info)
    {
        for (int i = 0; i < manager_get_time_slot_num(); i++)
        {
            if (sf_info[i].sf_send)
            {
                for (int j = 0; j < ul_subf_num; j++)
                {
                    rt_list_t *next_node = sf_info[i].sf_send[j].data_list.next;
                    while (next_node != &sf_info[i].sf_send[j].data_list)
                    {
                        data_node = rt_list_entry(next_node, sf_data_node_t, node);
                        dl_data = data_node->data;
                        manager_to_wiota_data_free(dl_data);
                        rt_free(data_node);
                        next_node = next_node->next;
                    }
                }

                rt_free(sf_info[i].sf_send);
                sf_info[i].sf_send = RT_NULL;
            }
        }
        rt_free(sf_info);
        sf_info = RT_NULL;
    }
}

/**
 * @brief 当ID资源耗尽时，有新终端接入，并开启和保活功能时调用
 *
 * @param dev_id             新终端设备ID
 * @return manager_address_t 新终端的地址信息
 */
manager_address_t *manager_alive_tick_check(unsigned int dev_id)
{
    unsigned int alive_timeout = uc_static_get_slot_send_cfg()->alive_timeout;
    if (alive_timeout == 0) // 保活功能未开启
    {
        return NULL;
    }

    manager_address_t *reserve_addr = RT_NULL;
    manager_list_t *auth_list = get_auth_list();
    manager_list_t *cur_list = RT_NULL;
    manager_list_t *next_node = RT_NULL;
    gateway_auth_node_t *auth_node = RT_NULL;
    unsigned int cur_tick = rt_tick_get();
    unsigned int diff_tick = 0;

    for (int i = 0; i < AUTH_LIST_LEN; i++)
    {
        cur_list = &auth_list[i];
        next_node = cur_list->next;
        while (next_node != cur_list)
        {
            auth_node = (gateway_auth_node_t *)next_node->data;
            diff_tick = get_diff_tick(cur_tick, auth_node->alive_tick);

            if (diff_tick > alive_timeout)
            {
                // 直接将超时节点的ID替换为新鉴权的ID
                TRACE_I("dev_id 0x%x timeout, replace to 0x%x, tick %u/%u", auth_node->dev_id, dev_id, cur_tick, auth_node->alive_tick);
                reserve_addr = manager_query_reserve_addr_by_dev_id(auth_node->dev_id);
                RT_ASSERT(reserve_addr != RT_NULL); // 必然不为空
                reserve_addr->dev_id = dev_id;

                // 替换信任列表
                auth_node->dev_id = dev_id;
                auth_node->is_online = 1;
                auth_node->alive_tick = cur_tick;

                return reserve_addr;
            }
            next_node = next_node->next;
        }
    }

    return RT_NULL;
}

/**
 * @brief 处理WIoTa启动完成的消息
 *
 * @param wiota_version WIoTa版本信息
 */
static void manager_handle_wiota_startup_msg(wiota_version_t *wiota_version)
{
    // 网关id管理初始化
    manager_gateway_userid_init();

    // 分时发送信息初始化
    manager_gateway_time_slot_init();

    // paging tx cache list初始化
    manager_paging_tx_cache_list_init();

    // 保存WIoTa版本信息到本地
    rt_memcpy(&g_wiota_version, wiota_version, sizeof(wiota_version_t));
    TRACE_I("wiota startup complete, wiota_version %s, cce_version 0x%x",
            wiota_version->uc8088_version, wiota_version->cce_version);

    manager_set_wiota_state(WIOTA_ONLINE);
    manager_set_ota_state(OTA_STATE_DEFAULE);

    // MQTT连接成功，上报网关和WIoTa基础配置到服务器
    if (MQTT_STATE_ONLINE == manager_get_mqtt_state())
    {
        if (GET_INFO_DEFAULT == manager_get_startup_info_state())
        {
            module_queue_communication(module_get_queue(NET_APP_MODULE),
                                       GATEWAY_MANAGER_MODULE,
                                       NET_APP_MODULE,
                                       ALL_CFG_GET,
                                       RT_NULL);
            manager_set_startup_info_state(GET_INFO_SUC);
        }
    }
    else
    {
        manager_set_startup_info_state(GET_INFO_WAIT);
    }

    // 创建点名定时器
    manager_roll_call_timer_create();

    rt_free(wiota_version);
}

/**
 * @brief 编码封装接口
 *
 * @param cmd            命令类型
 * @param response_flag  响应标志
 * @param gw_dev_id      网关设备地址
 * @param input_data     编码数据
 * @param input_data_len 编码数据长度
 * @param output_data    编码完成数据
 * @param output_len     编码完成数据长度
 * @return int           0表示成功，非0表示失败
 */
static int manager_coding_msg(int cmd, int response_flag, unsigned int gw_dev_id, void *input_data, int input_data_len, void **output_data, int *output_len)
{
    app_ps_header_t ps_header = {0};

    if (response_flag)
    {
        app_set_header_property(PRO_RESPONSE_FLAG, 1, &ps_header.property);
    }
    if (gw_dev_id)
    {
        app_set_header_property(PRO_SRC_ADDR, 1, &ps_header.property);
        ps_header.addr.src_addr = gw_dev_id;
    }

    ps_header.cmd_type = cmd;

    if (0 != app_data_coding(&ps_header, input_data, input_data_len, (unsigned char **)(output_data), (unsigned int *)output_len))
    {
        TRACE_E("%s line %d coding error", __FUNCTION__, __LINE__);
        return 1;
    }

    return 0;
}

/**
 * @brief 发送完成后处理结果回调
 *
 * @param buf 发送数据指针
 */
void manager_send_resp_result(void *buf)
{
    mng_to_wiota_data_t *operation_data = buf;
    unsigned int default_dev_addr = uc_static_get_gateway_base_cfg()->dev_id;

    // if (default_dev_addr != operation_data->head.src_address)
    // manager_response_message_result(operation_data->head.state, operation_data->head.request_number);
    // TODO: send to net

    if (RT_NULL != operation_data->data)
        rt_free(operation_data->data);

    if (RT_NULL != operation_data)
        rt_free(operation_data);
}

/**
 * @brief 发送鉴权请求消息给WIoTa APP线程，再由WIoTa APP线程调用WIoTa API接口发送数据
 *
 * @param state                鉴权状态
 * @param reallocated_wiota_id 重新分配的WIoTa id
 * @param time_slot_fn         分配的发送时隙
 * @param freq_list            网关的静态频点列表
 * @param cmd                  发送命令类型
 * @param wiota_addr           IoTE的设备地址，下行通讯时用
 * @return int                 0表示成功，非0表示失败
 */
static int manager_send_auth_res_msg(auth_state_e state,
                                     int reallocated_wiota_id,
                                     unsigned short time_slot_fn,
                                     char *freq_list,
                                     gateway_interaction_cmd_e cmd,
                                     unsigned int wiota_addr)
{
    char *msg;
    int msg_len;
    unsigned int gw_dev_id = uc_static_get_gateway_base_cfg()->dev_id;
    app_ps_auth_res_t auth_res = {0};

    // 填充鉴权响应
    auth_res.connect_index.state = state;
    auth_res.connect_index.time_slot_fn = time_slot_fn;
    auth_res.wiota_id = reallocated_wiota_id;
    rt_memcpy(auth_res.freq_list, freq_list, APP_MAX_FREQ_LIST_NUM);

    // 下行数据编码
    if (0 == manager_coding_msg(AUTHENTICATION_RES, 0, gw_dev_id, (void *)&auth_res, sizeof(app_ps_auth_res_t), (void **)&msg, &msg_len))
    {
        // 将编码完成后的数据发送给WIoTa APP线程
        if (0 != manager_send_to_wiota(GATEWAY_MANAGER_MODULE,
                                       cmd,
                                       0,
                                       gw_dev_id,
                                       wiota_addr,
                                       msg,
                                       msg_len,
                                       manager_send_resp_result))
        {
            rt_free(msg);
            return 1;
        }
    }

    return 0;
}

/**
 * @brief 处理鉴权请求消息
 *
 * @param dev_address   IoTE的设备id
 * @param wiota_address 鉴权请求时该地址和dev_address一致，用于发送鉴权响应
 * @param auth_req      鉴权请求结构体指针
 * @param rach_delay    接收到RACH消息的延时
 * @param len
 */
static void manager_handle_auth_requst_msg(unsigned int dev_address, unsigned int wiota_address, app_ps_auth_req_t *auth_req, unsigned char rach_delay)
{
    auth_state_e state = AUTHENTICATION_SUC;
    manager_address_t *reserve_addr = RT_NULL;
    unsigned int reallocated_wiota_id = 0;
    unsigned short time_slot_fn = 0;
    wiota_freq_cfg_t *freq_cfg = uc_static_get_wiota_freq_cfg();
    int is_no_data = 1;
    int is_auth_suc = 1;

    // 检查鉴权码是否合法
    if (0 == manager_check_key(auth_req->auth_code))
    {
        if (UC_TRANSMISSION_MODE != uc_static_get_gateway_auth_cfg()->work_mode)
        {
            // 鉴权通过，分配一个WIoTa id给该IoTE用于后续通讯
            reserve_addr = manager_reallocated_wiota_id(dev_address);
            if (RT_NULL != reserve_addr)
            {
                // 成功分配节点，将该IoTE加入信任设备列表，后续交互无需再次鉴权
                reserve_addr->rach_delay = rach_delay;
                reallocated_wiota_id = (reserve_addr->wiota_id | (1 << 31));
                time_slot_fn = reserve_addr->time_slot_fn;
                manager_add_trust_dev(dev_address);
                manager_roll_call_timer_start();
            }
            else
            {
                // 如果开启了保活功能，无资源分配时，遍历查找是否有alive_tick超时的节点，如果有则替换节点内容为新接入终端
                reserve_addr = manager_alive_tick_check(dev_address);
                if (reserve_addr)
                {
                    reserve_addr->rach_delay = rach_delay;
                    reallocated_wiota_id = (reserve_addr->wiota_id | (1 << 31));
                    time_slot_fn = reserve_addr->time_slot_fn;
                    is_no_data = 0;
                }
                else
                {
                    is_auth_suc = 0;
                }

                // 没开启保活功能或者开启保活功能，但所有节点均未超时，都认为分配失败，发送AUTHENTICATION_NO_DATA告知IoTE
                if (is_no_data)
                {
                    TRACE_E("reallocated wiota id fail, num %d-%d", manager_get_reallocated_num(), manager_get_actually_num());
                    state = AUTHENTICATION_NO_DATA;
                }
            }
        }

        if (is_auth_suc)
        {
            TRACE_I("0x%x is auth, wiota_id 0x%x, bi %d, si %d, sf %d, num %d-%d",
                    wiota_address, reallocated_wiota_id, reserve_addr->burst_idx, reserve_addr->slot_idx, time_slot_fn,
                    manager_get_reallocated_num(), manager_get_actually_num());
        }
    }
    else
    {
        // 鉴权码不合法，发送AUTHENTICATION_FAIL消息告知IoTE
        TRACE_E("manager_check_key fail");
        // 如果该IoTE曾存在于信任列表中，将其剔除，该种情况发生在网关鉴权码变动，通知IoTE后，IoTE未及时重新鉴权
        if (UC_TRANSMISSION_MODE != uc_static_get_gateway_auth_cfg()->work_mode)
        {
            manager_del_trust_dev(dev_address);
            reserve_addr = manager_query_reserve_addr_by_dev_id(dev_address);
            if (reserve_addr) // 可能为空，必须加判断
            {
                reserve_addr->allocate_flag = ADDRESS_RESERVED;
            }
        }
        state = AUTHENTICATION_FAIL;
    }

    // 发送鉴权响应给IoTE，分配给该IoTEWIoTa id、发送时隙time_slot_fn、频点列表freq_list
    manager_send_auth_res_msg(state, reallocated_wiota_id, time_slot_fn, freq_cfg->freq_list, WIOTA_APP_AUTH_RES, wiota_address);
}

/**
 * @brief 发送状态响应消息，如果需要响应，需在MQTT发送成功后将真实的发送结果回复给IoTE
 *
 * @param cmd        命令类型
 * @param state      状态类型
 * @param wiota_addr WIoTa地址
 * @param requst_num 请求计数
 * @return int       0表示成功，非0表示失败
 */
static int manager_send_response_state_msg(int cmd, int state, unsigned int wiota_addr, int requst_num)
{
    void *msg;
    int msg_len;
    unsigned char gw_verity = uc_static_get_gateway_auth_cfg()->gw_verity;
    unsigned int gw_dev_id = uc_static_get_gateway_base_cfg()->dev_id;

    if (0 == manager_coding_msg(cmd, 1, gw_verity ? gw_dev_id : 0, (void *)&state, 4, (void **)&msg, &msg_len))
    {
        if (manager_send_to_wiota(GATEWAY_MANAGER_MODULE,
                                  WIOTA_APP_MSG,
                                  0,
                                  gw_dev_id,
                                  wiota_addr,
                                  msg,
                                  msg_len,
                                  manager_send_resp_result))
        {
            rt_free(msg);
            TRACE_E("send_resp_state error");
            return 1;
        }
    }
    else
    {
        TRACE_E("manager_coding_msg error");
    }

    return 0;
}

/**
 * @brief 点名消息处理，根据鉴权信任列表发送空包，用于检测当前频点信号质量，如果发送失败较多则重新扫频
 *
 */
static void manager_handle_roll_call_msg(void)
{
    void *msg;
    int msg_len;
    unsigned char gw_verity = uc_static_get_gateway_auth_cfg()->gw_verity;
    unsigned int gw_dev_id = uc_static_get_gateway_base_cfg()->dev_id;
    manager_list_t *auth_list = get_auth_list();
    manager_list_t *cur_list = RT_NULL;
    manager_list_t *next_node = RT_NULL;
    gateway_auth_node_t *auth_node = RT_NULL;
    unsigned int wiota_addr = 0;

    // 遍历鉴权信任列表，并发送空包
    for (int i = 0; i < AUTH_LIST_LEN; i++)
    {
        cur_list = &auth_list[i];
        next_node = cur_list->next;
        while (next_node != cur_list)
        {
            auth_node = (gateway_auth_node_t *)next_node->data;
            wiota_addr = manager_query_wiota_id_by_dev_id(auth_node->dev_id);

            if (0 != manager_coding_msg(0xFF, 0, gw_verity ? gw_dev_id : 0, RT_NULL, 0, (void **)&msg, &msg_len))
            {
                TRACE_E("manager_coding_msg error");
                return;
            }
            if (0 != manager_send_to_wiota(GATEWAY_MANAGER_MODULE,
                                           WIOTA_APP_SEND_ROLL_CALL,
                                           0,
                                           gw_dev_id,
                                           wiota_addr,
                                           msg,
                                           msg_len,
                                           manager_send_resp_result))
            {
                continue;
            }
            else
            {
                manager_roll_call_total_num_inc();
                TRACE_D("send roll_call msg to dev_id 0x%x, num %d", auth_node->dev_id, manager_roll_call_total_num_get());
            }
            next_node = next_node->next;
        }
    }

    // 由于发送时非阻塞发送，通过工作队列延迟处理点名成功率的计算
    if (manager_roll_call_total_num_get() > 0)
    {
        manager_calc_roll_call_work();
    }

    return;
}

/**
 * @brief 处理IoTE版本验证消息，发送验证消息到服务器
 *
 * @param ps_header      协议头
 * @param version_verify 版本验证信息结构体指针
 */
static void manager_handle_version_verify_msg(app_ps_header_t ps_header, app_ps_version_verify_t *version_verify)
{
    ota_state_e ota_state = manager_get_ota_state();

    if (OTA_STATE_REQ != ota_state && OTA_STATE_STOP != ota_state)
    {
        TRACE_E("not require to handle version_verify, ota_state %d", ota_state);
        return;
    }

    mng_ul_version_verify_t *verify_info = rt_malloc(sizeof(mng_ul_version_verify_t));
    RT_ASSERT(verify_info);
    rt_memset(verify_info, 0, sizeof(mng_ul_version_verify_t));

    verify_info->head.cmd = VERSION_VERIFY;
    verify_info->head.src_addr = ps_header.addr.src_addr;
    verify_info->head.dest_num = 0;

    rt_memcpy(&verify_info->ver_info, version_verify, sizeof(app_ps_version_verify_t));

    if (0 != module_queue_communication(net_app_get_queue(),
                                        GATEWAY_MANAGER_MODULE,
                                        NET_APP_MODULE,
                                        NET_IOTE_VERSION_VERIFY,
                                        verify_info))
    {
        rt_free(verify_info);
    }
    TRACE_D("send version_verify to net suc");

    return;
}

/**
 * @brief 获取上行数据流向模块
 *
 * @return int 模块类型
 */
static int manager_get_to_module(void)
{
    int to_module = NET_APP_MODULE;
    int ul_data_flow = uc_static_get_gateway_data_cfg()->ul_data_flow;

    if (ul_data_flow == UC_UP_DATA_FLOW_TO_NET)
    {
        to_module = NET_APP_MODULE;
    }
    else if (ul_data_flow == UC_UP_DATA_FLOW_TO_UART)
    {
        to_module = SERIAL_485_MANAGER_MODULE;
    }
    else if (ul_data_flow == UC_UP_DATA_FLOW_TO_BT)
    {
        to_module = BT_MANAGER_MODULE;
    }
    else
    {
        TRACE_E("invalid data_flow %d", ul_data_flow);
        return -1;
    }

    return to_module;
}

/**
 * @brief 处理IoTE状态更新消息
 *
 * @param ps_header         网关协议头
 * @param state_update_data IoTE状态更新信息结构体指针
 */
static void manager_handle_iote_state_update_msg(app_ps_header_t ps_header, app_ps_iote_state_update_t *iote_state)
{
    int to_module = manager_get_to_module();
    if (to_module < 0)
    {
        return;
    }
    /*
        if (to_module == NET_APP_MODULE && MQTT_STATE_OFFLINE == manager_get_mqtt_state())
        {
            TRACE_D("mqtt offline, 0x%x iote_state is cached", ps_header.addr.src_addr);
            return;
        }
    */
    mng_ul_iote_state_t *to_net_state = rt_malloc(sizeof(mng_ul_iote_state_t));
    RT_ASSERT(to_net_state);
    rt_memset(to_net_state, 0, sizeof(mng_ul_iote_state_t));

    to_net_state->head.req_num = ps_header.packet_num;
    to_net_state->head.cmd = IOTE_STATE_UPDATE;
    to_net_state->head.src_addr = ps_header.addr.src_addr;
    rt_memcpy(&to_net_state->state, iote_state, sizeof(app_ps_iote_state_update_t));

    if (0 != module_queue_communication(module_get_queue(to_module),
                                        GATEWAY_MANAGER_MODULE,
                                        to_module,
                                        NET_IOTE_STATE_UPDATE,
                                        (void *)to_net_state))
    {
        TRACE_E("send iote_state_update to module %d fail", to_module);
        rt_free(to_net_state);
    }
}

static void manager_handle_iote_get_rtc_msg(unsigned int wiota_addr)
{
    char *msg;
    int msg_len;
    time_t timestamp = 0;
    unsigned char gw_verity = uc_static_get_gateway_auth_cfg()->gw_verity;
    unsigned int gw_dev_id = uc_static_get_gateway_base_cfg()->dev_id;

    get_timestamp(&timestamp);

    TRACE_D("get rtc %u to wiota 0x%x", timestamp, wiota_addr);

    // 下行数据编码
    if (0 == manager_coding_msg(IOTE_GET_RTC, 0, gw_verity ? gw_dev_id : 0, &timestamp, sizeof(time_t), (void **)&msg, &msg_len))
    {
        // 将编码完成后的数据发送给WIoTa APP线程
        if (0 != manager_send_to_wiota(GATEWAY_MANAGER_MODULE,
                                       WIOTA_APP_MSG,
                                       0,
                                       gw_dev_id,
                                       wiota_addr,
                                       msg,
                                       msg_len,
                                       RT_NULL))
        {
            rt_free(msg);
            return;
        }
    }
}

/**
 * @brief 网关管理线程发送用户透传数据给to_module线程发送结果回调函数
 *
 * @param data  发送给net的用户数据结构体指针
 * @param state 发送状态
 */
static void net_exec_result(void *data, net_send_result_e state)
{
    mng_ul_userdata_t *to_net_data = (mng_ul_userdata_t *)data;

    manager_send_response_state_msg(IOTE_USER_DATA, (int)state, to_net_data->head.wiota_addr, to_net_data->head.req_num);
}

/**
 * @brief 处理IoTE透传数据
 *
 * @param dev_addr   IoTE的设备地址
 * @param wiota_addr IoTE的WIoTa id
 * @param ps_header  网关协议头
 * @param data       数据指针
 * @param data_len   数据长度
 */
static void manager_handle_iote_user_data_msg(unsigned int dev_addr, unsigned int wiota_addr, app_ps_header_t ps_header, unsigned char *data, unsigned int data_len)
{
    int to_module = manager_get_to_module();
    if (to_module < 0)
    {
        return;
    }
    /*
        if (to_module == NET_APP_MODULE && MQTT_STATE_OFFLINE == manager_get_mqtt_state())
        {
            TRACE_D("mqtt offline, 0x%x user_data is cached", dev_addr);
            return;
        }
    */
    uc_up_encode_e format = uc_static_get_gateway_data_cfg()->up_encode;
    unsigned char ul_data_print = uc_static_get_gateway_data_cfg()->ul_data_print;
    int max_len = 640;    // len > 310 * 4 / 3 + 4 = 417 AND len > 310 * 2 = 620
    int length = max_len; // base64编码必须有足够空间否则返回ERR_BASE64_BUFFER_TOO_SMALL
    const char *fmt_str[] = {"string", "base64", "hex"};

    if (ul_data_print)
    {
        rt_kprintf("ul_data id %d, len %d\n", dev_addr, data_len);
        manager_printf_data_hex(data, data_len);
    }
    mng_ul_userdata_t *to_net_data = rt_malloc(sizeof(mng_ul_userdata_t) + max_len);

    RT_ASSERT(to_net_data);
    rt_memset(to_net_data, 0, sizeof(mng_ul_userdata_t) + max_len);

    to_net_data->head.req_num = ps_header.packet_num;
    to_net_data->head.cmd = IOTE_USER_DATA;
    to_net_data->head.dest_addr = RT_NULL;
    to_net_data->head.src_addr = dev_addr;
    to_net_data->head.wiota_addr = wiota_addr;

    // 需要响应设置回调，当to_module发送成功执行回调返回发送结果
    if (ps_header.property.is_need_res)
    {
        to_net_data->result_function = net_exec_result;
    }
    else
    {
        to_net_data->result_function = RT_NULL;
    }

    rt_memcpy(to_net_data->fmt, fmt_str[format], rt_strlen(fmt_str[format]));
    switch (format)
    {
    case UC_UP_ENCODE_NONE:
        // String 编码
        rt_memcpy(to_net_data->data, data, data_len);
        to_net_data->data_len = data_len;
        break;

    case UC_UP_ENCODE_BASE64:
        // Base64 编码
        tiny_base64_encode((unsigned char *)to_net_data->data, &length, data, data_len);
        to_net_data->data_len = length;
        break;

    case UC_UP_ENCODE_HEX:
        // Hex 编码
        hex_encode(to_net_data->data, data, data_len);
        to_net_data->data_len = data_len * 2;
        break;

    default:
        break;
    }

    // 将透传数据发送到to_module线程
    if (0 != module_queue_communication(module_get_queue(to_module),
                                        GATEWAY_MANAGER_MODULE,
                                        to_module,
                                        NET_IOTE_USER_DATA,
                                        (void *)to_net_data))
    {
        TRACE_E("send iote_user_data to module %d fail", to_module);
        rt_free(to_net_data);
    }
}

/**
 * @brief 处理终端版本号查询响应消息
 *
 * @param iote_ver 终端版本信息
 */
static void manager_handle_iote_version_response_msg(app_ps_iote_version_t *iote_ver)
{
    mng_ul_iote_version_t *to_net_version = rt_malloc(sizeof(mng_ul_iote_version_t));
    RT_ASSERT(to_net_version);
    rt_memset(to_net_version, 0, sizeof(mng_ul_iote_version_t));

    to_net_version->head.cmd = IOTE_VERSION_RES;
    rt_memcpy(&to_net_version->iote_ver, iote_ver, sizeof(app_ps_iote_version_t));

    if (0 != module_queue_communication(net_app_get_queue(),
                                        GATEWAY_MANAGER_MODULE,
                                        NET_APP_MODULE,
                                        NET_IOTE_VERSION_RES,
                                        (void *)to_net_version))
    {
        TRACE_E("send iote_version to net fail");
        rt_free(to_net_version);
    }
}

/**
 * @brief 处理WIoTa APP发送的上行接收消息的接口
 *
 * @param to_mng_data WIoTa APP线程发送给管理线程的数据指针
 */
static void manager_handle_recv_data_msg(wiota_to_mng_data_t *to_mng_data)
{
    unsigned char *decode_data = RT_NULL;
    unsigned int decode_data_len = 0;
    app_ps_header_t ps_header = {0};
    int decoding_res = 0;
    unsigned char gw_verity = uc_static_get_gateway_auth_cfg()->gw_verity;
    unsigned int gw_dev_id = uc_static_get_gateway_base_cfg()->dev_id;

    // 解码得到网关头ps_header、数据decode_data和数据长度decode_data_len
    decoding_res = app_data_decoding((unsigned char *)to_mng_data->data, to_mng_data->data_len, &decode_data, &decode_data_len, &ps_header);
    if (0 != decoding_res || 0 == decode_data_len || RT_NULL == decode_data)
    {
        TRACE_E("recv_data_msg decoding failed");
        wiota_to_manager_data_free(to_mng_data);
        return;
    }

    // 开启网关校验后，收到非自己ID的数据，丢弃
    if (gw_verity && ps_header.cmd_type != AUTHENTICATION_REQ)
    {
        if (ps_header.addr.dest_addr != gw_dev_id)
        {
            TRACE_E("recv illegal iote 0x%x ul data, discard, dest_addr 0x%x\n", to_mng_data->id, ps_header.addr.dest_addr);
            wiota_to_manager_data_free(to_mng_data);
            rt_free(decode_data);
            return;
        }
    }

    // 非透传模式才需要查询id和分配id
    if (UC_TRANSMISSION_MODE != uc_static_get_gateway_auth_cfg()->work_mode)
    {
        if (0 == ps_header.property.is_src_addr &&
            0 != to_mng_data->id &&
            AUTHENTICATION_REQ != ps_header.cmd_type)
        {
            // 非鉴权请求消息，查询该id是否合法（已经鉴权）
            ps_header.addr.src_addr = manager_query_dev_id_by_wiota_id(to_mng_data->id);
        }

        // 非鉴权请求消息，id不合法（查询未在信任列表中）
        if (AUTHENTICATION_REQ != ps_header.cmd_type &&
            0 != manager_query_trust_dev(ps_header.addr.src_addr))
        {
            wiota_freq_cfg_t *freq_cfg = uc_static_get_wiota_freq_cfg();

            TRACE_W("src_addr 0x%x, must restart auth", ps_header.addr.src_addr);

            // 接收到一个非法IoTE的数据，要求其重新鉴权
            manager_send_auth_res_msg(AUTHENTICATION_FAIL, 0, 0, freq_cfg->freq_list, WIOTA_APP_MSG, to_mng_data->id);
            wiota_to_manager_data_free(to_mng_data);
            rt_free(decode_data);
            return;
        }
    }

    if (!ps_header.property.response_flag)
    {
        send_led_event(LED_WIOTA, LED_E_BLINK);
        // TRACE_I("recv 0x%x cmd %d", ps_header.addr.src_addr, ps_header.cmd_type);
        switch (ps_header.cmd_type)
        {
        case AUTHENTICATION_REQ:
            TRACE_I("rcv 0x%x cmd AUTHENTICATION_REQ", ps_header.addr.src_addr);
            manager_handle_auth_requst_msg(ps_header.addr.src_addr, to_mng_data->id, (app_ps_auth_req_t *)decode_data, to_mng_data->delay);
            break;

        case VERSION_VERIFY:
            TRACE_I("rcv 0x%x cmd VERSION_VERIFY", ps_header.addr.src_addr);
            manager_handle_version_verify_msg(ps_header, (app_ps_version_verify_t *)decode_data);
            break;

        case IOTE_MISSING_DATA_REQ:
            TRACE_I("rcv 0x%x cmd IOTE_MISSING_DATA_REQ", ps_header.addr.src_addr);
            manager_handle_missing_data_req_msg((app_ps_missing_data_req_t *)decode_data);
            break;

        case IOTE_STATE_UPDATE:
            TRACE_I("rcv 0x%x cmd IOTE_STATE_UPDATE", ps_header.addr.src_addr);
            manager_handle_iote_state_update_msg(ps_header, (app_ps_iote_state_update_t *)decode_data);
            break;

        case IOTE_GET_RTC:
            TRACE_I("rcv 0x%x cmd IOTE_GET_RTC", ps_header.addr.src_addr);
            manager_handle_iote_get_rtc_msg(to_mng_data->id);
            break;

        case IOTE_USER_DATA:
            TRACE_I("rcv 0x%x-%d(0x%x) cmd IOTE_USER_DATA, len %d", ps_header.addr.src_addr, ps_header.addr.src_addr, to_mng_data->id, decode_data_len);
            manager_handle_iote_user_data_msg(ps_header.addr.src_addr, to_mng_data->id, ps_header, decode_data, decode_data_len);
            manager_send_cache_paging_tx_uc_data(ps_header.addr.src_addr);
            break;

        case IOTE_VERSION_RES:
            TRACE_I("rcv 0x%x cmd IOTE_VERSION_RES", ps_header.addr.src_addr);
            manager_handle_iote_version_response_msg((app_ps_iote_version_t *)decode_data);
            break;

        default:
            TRACE_E("rcv err 0x%x cmd %d", ps_header.addr.src_addr, ps_header.cmd_type);
            break;
        }
    }

    wiota_to_manager_data_free(to_mng_data);
    rt_free(decode_data);
}

static void manager_send_paging_tx_uc_data_work(struct rt_work *work, void *work_data)
{
    unsigned int dev_id = (unsigned int)work_data;

    manager_send_cache_paging_tx_uc_data(dev_id);

    rt_free(work);
}

/**
 * @brief  处理wiota设备状态更新消息
 *
 * @param  dev_status 设备状态信息
 */
static void manager_handle_status_report_msg(device_status_t *dev_status)
{
    int to_module = manager_get_to_module();
    if (to_module < 0)
    {
        return;
    }

    // if (to_module == NET_APP_MODULE && MQTT_STATE_OFFLINE == manager_get_mqtt_state())
    // {
    //     TRACE_D("mqtt offline, 0x%x status_report is cached", dev_status->dev_id);
    //     rt_free(dev_status);
    //     return;
    // }

    mng_ul_device_status_t *to_net_data = rt_malloc(sizeof(mng_ul_device_status_t));
    RT_ASSERT(to_net_data);
    rt_memset(to_net_data, 0, sizeof(mng_ul_device_status_t));

    to_net_data->cmd = PROT_DEVICE_STATUS;
    to_net_data->dev_id = dev_status->dev_id;
    to_net_data->status = dev_status->status;

    // 将透传数据发送到to_module线程
    if (0 != module_queue_communication(module_get_queue(to_module),
                                        GATEWAY_MANAGER_MODULE,
                                        to_module,
                                        DEVICE_STATUS_GET,
                                        (void *)to_net_data))
    {
        TRACE_E("send status_report to module %d fail", to_module);
        rt_free(to_net_data);
    }

    if (manager_get_cache_paging_tx_uc_data(dev_status->dev_id))
    {
        // 鉴权成功之后，如果有缓存的paging tx单播数据，则延迟一点时间发送，延迟的目的是等待终端重设userid和保存静态数据，如果不延迟立即发送的话，必然会发送失败
        struct rt_work *pt_uc_work = rt_malloc(sizeof(struct rt_work));
        RT_ASSERT(pt_uc_work);

        int delay = 1000; // delay 1s
        rt_work_init(pt_uc_work, manager_send_paging_tx_uc_data_work, (void *)dev_status->dev_id);
        rt_work_submit(pt_uc_work, delay);
        TRACE_D("submit pt_uc_work, delay %d", delay);
    }

    rt_free(dev_status);
}

/**
 * @brief 处理来自WIoTa APP线程发送的消息接口，称为上行通路
 *
 * @param cmd  WIoTa上行命令
 * @param data WIoTa上行数据
 */
void manager_handle_uplink_msg(int cmd, void *data)
{
    // TRACE_I("mng ul recv cmd 0x%x", cmd);

    switch (cmd)
    {
    case WIOTA_START:
        TRACE_I("mng ul WIOTA_START");
        manager_handle_wiota_startup_msg((wiota_version_t *)data);
        break;

    case WIOTA_RECV_DATA:
        TRACE_I("mng ul WIOTA_RECV_DATA");
        manager_handle_recv_data_msg((wiota_to_mng_data_t *)data);
        break;

    case WIOTA_ABNORMAL_EXIT:
        TRACE_I("mng ul WIOTA_ABNORMAL_EXIT");
        manager_roll_call_timer_del();
        manager_set_wiota_state(WIOTA_OFFLINE);
        manager_set_userid_manager_state(USERID_MANAGE_DEFAULT);
        manager_gateway_time_slot_deinit();
        manager_paging_tx_cache_list_deinit();
        if (UC_TRANSMISSION_MODE != uc_static_get_gateway_auth_cfg()->work_mode)
        {
            manager_clean_trust_dev();
            manager_wiota_userid_deinit();
        }
        break;

    case WIOTA_ROLL_CALL:
        TRACE_I("mng ul WIOTA_ROLL_CALL");
        manager_handle_roll_call_msg();
        break;

    case WIOTA_STATUS_REPORT:
        TRACE_I("mng ul WIOTA_STATUS_REPORT");
        manager_handle_status_report_msg((device_status_t *)data);
        break;

    case AUTH_INFO_CHANGE:
    {
        wiota_freq_cfg_t *freq_cfg = uc_static_get_wiota_freq_cfg();
        TRACE_I("mng ul AUTH_INFO_CHANGE");

        // 鉴权信息更改，发送广播通知IoTE重新鉴权.
        // 此信息会造成IOTE v3.2和dtu v3.3.6以前的版本频点被篡改。
        // 如果终端掉线会自动重新鉴权。如果业务正常，可以不用理会修改频点等信息。
        // manager_send_auth_res_msg(AUTHENTICATION_INFO_CHANGE, 0, 0, freq_cfg->freq_list, WIOTA_APP_SEND_OTA, 0);
    }
    break;

    default:
        break;
    }
}